
#include<stdio.h>
#include<stdlib.h>

#include"glheader.h"

#include"vmatrix.h"

VMatrix * vmatrix;

bool mat_equal (float * m1, float * m2)
{
  for(int i=0;i<16;i++){
    if(m1[i]!=m2[i])
      return false;
  }
  return true;
}

void test_eq (float * m1, float * m2)
{
  static int cont=1;
  bool res = mat_equal(m1,m2);
  printf("test_eq %d %s\n",cont,res?"true":"false");
  if(!res){
    for(int i=0;i<16;i++){
      if(m1[i]!=m2[i])
        printf("[%d] %f %f %f\n",i,m1[i],m2[i],m1[i]-m2[i]);
    }
  }
  cont++;
}

void stack_test ()
{
  printf("STACK_TEST-------------------------\n");
  float m1[16] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
  float m2[16] = {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
  float m3[16] = {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3};
  float m4[16] = {4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4};
	float mtest[16];
  vmatrix->LoadMatrix(m4);
  vmatrix->Push();
  vmatrix->LoadMatrix(m3);
  vmatrix->Push();
  vmatrix->LoadMatrix(m2);
  vmatrix->Push();
  vmatrix->LoadMatrix(m1);
  //test1
  vmatrix->GetMatrix(mtest);
  test_eq(m1,mtest);
  //test1
  vmatrix->Pop();
  vmatrix->GetMatrix(mtest);
  test_eq(m2,mtest);
  //test1
  vmatrix->Pop();
  vmatrix->GetMatrix(mtest);
  test_eq(m3,mtest);
  //test1
  vmatrix->Pop();
  vmatrix->GetMatrix(mtest);
  test_eq(m4,mtest);
  //test push copy
  vmatrix->Push();
  vmatrix->Push();
  vmatrix->GetMatrix(mtest);
  test_eq(m4,mtest);
  vmatrix->Pop();
  vmatrix->GetMatrix(mtest);
  test_eq(m4,mtest);
  vmatrix->Pop();
}

static float gl_mat[16], vm_mat[16];

void comp_gl_vm ()
{
  vmatrix->GetMatrix(vm_mat);
	glGetFloatv(GL_MODELVIEW_MATRIX, gl_mat);
  test_eq(gl_mat,vm_mat);
}

void gl_test ()
{
  printf("GL_TEST-------------------------\n");
  glMatrixMode(GL_MODELVIEW);
  //LoadIdentity
  printf("LoadIdentity\n");
  vmatrix->LoadIdentity();
  glLoadIdentity();
  comp_gl_vm();
  //Translate
  printf("Translate\n");
  glTranslatef(10,20,30);
  vmatrix->Translate(10,20,30);
  comp_gl_vm();
  //Rotate
  printf("Rotate\n");
  glRotatef(45,0,0,1);
  vmatrix->Rotate(45,0,0,1);
  glRotatef(30,0,1,0);
  vmatrix->Rotate(30,0,1,0);
  comp_gl_vm();
  //Scale
  printf("Scale\n");
  glScalef(10,20,30);
  vmatrix->Scale(10,20,30);
  comp_gl_vm();
  //LookAt
  printf("LookAt\n");
  float xcenter = 40, ycenter=50, zcenter=20, zdist=100;
  gluLookAt(xcenter, ycenter, zcenter-zdist,
            xcenter, ycenter, zcenter,
            0.0f, 1.0f, 0.0f
           );
  vmatrix->LookAt(xcenter, ycenter, zcenter-zdist,
            xcenter, ycenter, zcenter,
            0.0f, 1.0f, 0.0f
           );
  comp_gl_vm();
  //GetMatrixIT
  printf("GetMatrixIT\n");
  vmatrix->GetMatrixIT(vm_mat);
  glMultTransposeMatrixf(vm_mat);
  vmatrix->LoadIdentity();
  comp_gl_vm();
  //Frustum
  printf("Frustum\n");
  vmatrix->LoadIdentity();
  glLoadIdentity();
  glFrustum(-30,60,-90,100,10,1000);
  vmatrix->Frustum(-30,60,-90,100,10,1000);
  comp_gl_vm();
  //Perspective
  printf("Perspective\n");
  vmatrix->LoadIdentity();
  glLoadIdentity();
  gluPerspective(45,2,10,1000);
  vmatrix->Perspective(45,2,10,1000);
  comp_gl_vm();
}

static void Redraw ()
{
  gl_test();
  delete vmatrix;
  exit(0);
}

int main(int argc,char** argv)
{
  vmatrix = new VMatrix();
  stack_test();
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB);
  glutInitWindowSize(800,800);
  glutCreateWindow("test");
  glutDisplayFunc(Redraw);
  glutMainLoop();
}
